package cn.lingyangwl.agile.infra.datamanage.db.mysql;

import cn.lingyangwl.agile.infra.datamanage.db.GeneratorConfig;
import cn.lingyangwl.agile.infra.module.datamanage.db.TableIndexDefinition;
import cn.lingyangwl.agile.infra.datamanage.db.TableIndexSelector;
import cn.lingyangwl.framework.tool.core.StringUtils;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author shenguangyang
 */
public class MysqlTableIndexSelector extends TableIndexSelector {
    public MysqlTableIndexSelector(GeneratorConfig generatorConfig) {
        super(generatorConfig);
    }
    private static final String SHOW_SQL = "SHOW INDEX FROM %s";
    private static final String UNIQUE = "1";
    private static final String NORMAL = "0";

    @Override
    protected String getTableIndexInfoSQL(String tableName) {
        return String.format(SHOW_SQL, tableName);
    }

    @Override
    protected List<TableIndexDefinition> buildTableIndexDefinition(List<Map<String, Object>> rowMapList) {
        List<TableIndexDefinition> respList = new ArrayList<>();
        List<IndexData> tempList = new ArrayList<>();
        for (Map<String, Object> rowMap : rowMapList) {
            // 排除主键
            IndexData temp = new IndexData();
            temp.setName(String.valueOf(rowMap.get("KEY_NAME")));
            if (temp.getName().equalsIgnoreCase("PRIMARY")) {
                continue;
            }

            String nonUnique = String.valueOf(rowMap.get("NON_UNIQUE"));
            if (UNIQUE.equalsIgnoreCase(nonUnique)) {
                temp.setType("UNIQUE");
            } else if (NORMAL.equalsIgnoreCase(nonUnique)) {
                temp.setType("NORMAL");
            }

            String indexType = String.valueOf(rowMap.get("INDEX_TYPE"));
            if ("BTREE".equalsIgnoreCase(indexType)) {
                temp.setMethod("BTREE");
            }
            if ("FULLTEXT".equalsIgnoreCase(indexType)) {
                temp.setType("FULLTEXT");
            }
            temp.setTableName(String.valueOf(rowMap.get("TABLE")));
            temp.setSeqInIndex(Integer.valueOf(String.valueOf(rowMap.get("SEQ_IN_INDEX"))));
            temp.setComment(String.valueOf(rowMap.get("INDEX_COMMENT")));
            temp.setColumnNames(String.valueOf(rowMap.get("COLUMN_NAME")));
            tempList.add(temp);
        }
        Map<String, List<IndexData>> groupMap = tempList.stream()
                .collect(Collectors.groupingBy(TableIndexDefinition::getName));
        for (Map.Entry<String, List<IndexData>> entry : groupMap.entrySet()) {
            List<IndexData> collect = entry.getValue().stream()
                    .sorted(Comparator.comparing(IndexData::getSeqInIndex)).collect(Collectors.toList());
            collect.stream().findFirst().ifPresent((x) -> {
                x.setColumnNames(
                        StringUtils.toStr(
                                collect.stream()
                                        .map(TableIndexDefinition::getColumnNames)
                                        .collect(Collectors.toList()), ",")
                );
                respList.add(x);
            });
        }
        return respList;
    }

    @Getter
    @Setter
    private static class IndexData extends TableIndexDefinition {
        private Integer seqInIndex;
    }
}
